/*
 * Copyright (c) 2025 lhjhit
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
// #include <zephyr/sys/printk.h>
#include <zephyr/drivers/adc.h>

#include "adc.h"

LOG_MODULE_REGISTER(ADC_MODULE, LOG_LEVEL_INF);

/* ADC node from the devicetree. */
#define ADC_NODE DT_ALIAS(adc0)

/* Data of ADC device specified in devicetree. */
static const struct device *adc = DEVICE_DT_GET(ADC_NODE);

/* Data array of ADC channels for the specified ADC. */
static const struct adc_channel_cfg channel_cfgs[] = {
	DT_FOREACH_CHILD_SEP(ADC_NODE, ADC_CHANNEL_CFG_DT, (,))};

/* Get the number of channels defined on the DTS. */
#define CHANNEL_COUNT ARRAY_SIZE(channel_cfgs)

/* Data array of ADC channel voltage references. */
static uint32_t vrefs_mv[CHANNEL_COUNT];

uint16_t battery_voltage = 0;
bool value_is_ready = false;

void thread_adc(void *p1, void *p2, void *p3)
{
	int ret;
	uint32_t val_mv;
	uint32_t val_mv_total;
	uint32_t val_mv_ave;

	ARG_UNUSED(p1);
	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

#ifdef CONFIG_SEQUENCE_32BITS_REGISTERS
	uint32_t channel_reading[CONFIG_SEQUENCE_SAMPLES][CHANNEL_COUNT];
#else
	uint16_t channel_reading[CONFIG_SEQUENCE_SAMPLES][CHANNEL_COUNT];
#endif

	/* Options for the sequence sampling. */
	const struct adc_sequence_options options = {
		.extra_samplings = CONFIG_SEQUENCE_SAMPLES - 1,
		.interval_us = 0,
	};

	/* Configure the sampling sequence to be made. */
	struct adc_sequence sequence = {
		.buffer = channel_reading,
		/* buffer size in bytes, not number of samples */
		.buffer_size = sizeof(channel_reading),
		.resolution = CONFIG_SEQUENCE_RESOLUTION,
		.options = &options,
	};

	if (!device_is_ready(adc)) {
		LOG_ERR("ADC controller device %s not ready\n", adc->name);
		return;
	}

	/* Configure channels individually prior to sampling. */
	for (size_t i = 0U; i < CHANNEL_COUNT; i++) {
		sequence.channels |= BIT(channel_cfgs[i].channel_id);
		ret = adc_channel_setup(adc, &channel_cfgs[i]);
		if (ret < 0) {
			LOG_ERR("Could not setup channel #%d (%d)\n", i, ret);
			return;
		}
		vrefs_mv[i] = adc_ref_internal(adc);
	}

	while (true) {

		ret = adc_read(adc, &sequence);
		if (ret < 0) {
			LOG_ERR("Could not read (%d)\n", ret);
			continue;
		}

		for (size_t channel_index = 0U; channel_index < CHANNEL_COUNT; channel_index++) {

			val_mv_total = 0;
			val_mv_ave = 0;

			// LOG_INF("- %s, channel %" PRId32 ", %" PRId32 " sequence samples:\n",
			//        adc->name, channel_cfgs[channel_index].channel_id,
			//        CONFIG_SEQUENCE_SAMPLES);
			for (size_t sample_index = 0U; sample_index < CONFIG_SEQUENCE_SAMPLES;
			     sample_index++) {
				
				val_mv = channel_reading[sample_index][channel_index];
				// LOG_INF("- - %" PRId32, val_mv);

				ret = adc_raw_to_millivolts(vrefs_mv[channel_index],
							    channel_cfgs[channel_index].gain,
							    CONFIG_SEQUENCE_RESOLUTION, &val_mv);

				/* conversion to mV may not be supported, skip if not */
				if ((ret < 0) || vrefs_mv[channel_index] == 0) {
					LOG_ERR(" (value in mV not available)\n");
				} else {
					// LOG_INF(" = %" PRId32 "mV\n", val_mv);
				}

				val_mv_total = val_mv_total + val_mv;
				val_mv_ave = val_mv_total/(sample_index + 1);
				// LOG_INF(" = %" PRId32 "mV\n", val_mv_ave);
			}

			// val_mv_ave = val_mv_total/5;
			if (channel_index == 1) {
				battery_voltage = val_mv_ave * RATIO;
				LOG_INF(" = %" PRId32 "mV\n", battery_voltage);
			}
		}

		value_is_ready = true;
		k_sleep(K_SECONDS(20));
	}
}